let num=ref(0)
let obj=reactive({num})
console.log(obj.num) //读取时会解包 0
obj.num=3 // 相当于直接给ref的num赋值

const objr2= reactive({count:ref(1)})
let {count}=objr2  count在模版使用失去响应式 

let num=ref(0)
let obj=reactive([num]) //reactive 的值是一个数组时下面也不会解包
console.log(obj[0])  //不会解包
obj[0].value=4 //想要给num赋值时需要用到.value
obj[0]=6 //会脱离ref,断开引用 此时的修改与num无关了

let {count}=ref({count:0}) //不能解构此时没有count属性
此时需要
let obj=ref({count:0}) 
obj.value.count=3
其实obj.value就是一个reactive的对象
let obj={count:0}
let refobj=ref(obj)
console.log(refobj.value===reactive(obj)) //true  

reactive传入同一个对象引用时返回 反向相同的proxy代理  
let obj={count:0}
console.log(reactive(obj)===reactive(obj)) //true

const obj1={ count: 0 }
const objr1 = reactive(obj1)
obj1.count=7
console.log(objr1.count) //7 因为代理对象始终从原始对象上拿属性

key的出现是为了更精确的找到可以重用的dom进行更新
如果不使用key 会采用就地更新(按照位置index,复用之前的dom)的原则复用所有现有的dom  ***如果里面包含有状态dom，或者子组件有自己的状态将导致无法更新***

onMounted 周期内可以从document 拿到元素 （v2 不可以）

父与子更新顺序
    parent onBeforeUpdate
       child onBeforeUpdate
       child onUpdated
    parent onUpdated
props验证器只是提示错误，validator返回false时 模版依然可以拿到propF的值
   defineProps({
   propF: {
      type:String,
      validator(value:string, props) {


const state = reactive({
  foo: 1,
  bar: 2
})
// 双向 ref，会与源属性同步
const fooRef = toRef(state, 'foo') //get 的时候直接从state拿foo属性（然后触发依赖），修改时候直接修改state的foo属性
const stateAsRefs = toRefs(state) //stateAsRefs.foo 直接指向一个ref 也直接从state拿值和该值 **stateAsRefs.foo不会直接解包，操作是需要访问value属性**

const shallow = shallowRef({
  greet: 'Hello, world'
})
watchEffect(() => {
  console.log(shallow.value.greet)
})
shallow.value.greet = 'Hello, universe' 不会触发watchEffect
triggerRef(shallow) 会触发watchEffect 如果此时页面也有使用这个属性会触发页面更新

shallowReactive  一个浅层响应式对象里只有根级别的属性是响应式的。属性的值会被原样存储和暴露，这也意味着值为 ref 的属性不会被自动解包了
shallowReadonly  只有根层级的属性变为了只读。属性的值都会被原样存储和暴露，这也意味着值为 ref 的属性不会被自动解包了。
readonly 也会自动解包
   const ref1=ref(1)
   const obj5={ref:{ref1}}
   const copy = readonly(obj5)
   console.log(copy.ref.ref1)
toRaw 无论代理多少层都返回最原始的对象
   let obj2={name:'liu'}
   let objr3=reactive(obj2)
   let objr4=shallowReactive(objr3)
   let objr5=readonly(objr4) 
   console.log(toRaw(objr5)===obj2);
markRaw 使一个对象不能被代理  在一个对象上面添加 __v_skip属性 
   const obj4={name:'nihao'}
   markRaw(obj4)   //{name: 'nihao', __v_skip: true}
   console.log(isReactive(reactive(obj4)),obj4) // false
   const foo = markRaw({})
   console.log(isReactive(reactive(foo))) // false
   // 也适用于嵌套在其他响应性对象
   const bar = reactive({ foo })
   console.log(isReactive(bar.foo)) // false
  如果一个对象已经是代理对象会在原始对象上添加 __v_skip属性 返回代理对象 
   const obj4={name:'how are you'}
   const objr6=reactive(obj4)
   const objm= markRaw(objr6)
   console.log(objm===objr6)
   const objr7=reactive(objm)
   console.log(objr7===objr6) // true
   console.log(isReactive(obj4)) //false
   console.log(isReactive(objm)) //true
   setTimeout(() => {
   objm.name='都挺好' //对象仍然是响应式
   }, 1000);
